package com.suredy.app.porject.tools;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 文件存储工具类
 * 
 * @author VIVID.G
 * @since 2015-10-26
 * @version v0.1
 */
@Component
public class FileTool {

	private final static Logger log = LoggerFactory.getLogger(FileTool.class);

	@Value("${files.container_folder}")
	private String ROOT_DIR;

	/* 默认目录 */
	private final String TMP_DIR = "tmp_dir";

	/* 缓存大小，默认4K */
	private final int BUFFER_SIZE = 1024 * 4;

	/**
	 * 初始化
	 */
	@PostConstruct
	protected void init() {
		if (StringUtils.isBlank(this.ROOT_DIR))
			throw new RuntimeException("Files storage DIR is empty! Please check the config file 'system.properties'");

		if (!this.ROOT_DIR.endsWith(File.separator))
			this.ROOT_DIR += File.separator;

		this.mkDirs(this.ROOT_DIR);
	}

	/**
	 * 获取文件存储的根目录
	 * 
	 * @return
	 */
	public String rootDIR() {
		return this.ROOT_DIR;
	}

	/**
	 * 存储文件到服务器本地磁盘
	 * 
	 * @param in
	 * @param key
	 * @return
	 * @throws IOException
	 */
	public File store(final InputStream in, String key) {
		if (in == null)
			return null;

		if (StringUtils.isBlank(key))
			key = this.TMP_DIR;

		String dir = this.ROOT_DIR + key + File.separator;

		if (!this.mkDirs(dir))
			throw new RuntimeException("Create folder error.");

		File file = this.newFile(dir);

		byte[] buffer = new byte[BUFFER_SIZE];
		int size = -1;
		BufferedOutputStream out = null;

		try {
			out = new BufferedOutputStream(new FileOutputStream(file));

			while ((size = in.read(buffer)) != -1) {
				out.write(buffer, 0, size);

				out.flush();
			}

			return file;
		} catch (IOException e) {
			log.error("Write to file error", e);
		} finally {
			try {
				if (out != null)
					out.close();

				if (in != null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return null;
	}

	public long output(final HttpServletRequest request, final HttpServletResponse response, String relativePath) throws IOException {
		if (request == null || response == null || StringUtils.isBlank(relativePath))
			return -1;

		File file = new File(this.ROOT_DIR + relativePath);

		// 文件不存在
		if (!file.isFile())
			return -1;

		response.setHeader("Content-Length", "" + file.length());

		OutputStream out = null;
		InputStream in = null;
		long readed = 0;

		try {
			out = response.getOutputStream();
			in = new FileInputStream(file);
			byte[] buffer = new byte[this.BUFFER_SIZE];
			int size = -1;

			while ((size = in.read(buffer)) != -1) {
				out.write(buffer, 0, size);

				readed += size;
			}
		} catch (IOException e) {
			log.error("Output file on http error.", e);
		} finally {
			if (out != null)
				out.close();

			if (in != null)
				in.close();
		}

		return readed;
	}

	/**
	 * 获取本地存储文件的相对路径
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public String relativelyPath(File file) throws IOException {
		if (file == null || !file.isFile())
			return null;

		String path = file.getCanonicalPath();

		if (StringUtils.isBlank(path))
			return null;

		path = path.replace(this.ROOT_DIR, "");

		return path;
	}

	/**
	 * 通过相对路径删除文件
	 * 
	 * @param relativelyPath
	 * @return
	 */
	public boolean removeByRelativelyPath(String relativelyPath) {
		if (StringUtils.isBlank(relativelyPath))
			return false;

		String path = this.ROOT_DIR + relativelyPath;

		File file = new File(path);

		if (!file.isFile())
			return false;

		if (file.delete()) {
			File folder = file.getParentFile();

			// 删除空的父文件夹
			if (folder.listFiles().length <= 0)
				folder.delete();
		}

		return true;
	}

	/**
	 * 创建文件夹
	 * 
	 * @param dir
	 * @return
	 */
	private boolean mkDirs(String dir) {
		if (StringUtils.isBlank(dir))
			return false;

		File folder = new File(dir);

		if (folder.isDirectory())
			return true;

		return folder.mkdirs();
	}

	/**
	 * 获取一个新的UUID
	 * 
	 * @return
	 */
	private String newId() {
		return UUID.randomUUID().toString().replace("-", "");
	}

	/**
	 * 创建新文件
	 * 
	 * @param dir
	 * @return
	 */
	private File newFile(String dir) {
		if (StringUtils.isBlank(dir))
			return null;

		if (!dir.endsWith(File.separator))
			dir += File.separator;

		return new File(dir + this.newId());
	}

}
